<template>
  <div
    v-clickoutside="handleClose"
    class="el-select"
    :class="[selectSize ? 'el-select--' + selectSize : '']"
    @click.stop="toggleMenu"
  >
    <div
      v-if="multiple"
      ref="tags"
      class="el-select__tags"
      :style="{ 'max-width': inputWidth - 32 + 'px', width: '100%' }"
    >
      <span v-if="collapseTags && selected.length">
        <c-tag
          :closable="!selectDisabled"
          :size="collapseTagSize"
          :hit="selected[0].hitState"
          type="info"
          disable-transitions
          @close="deleteTag($event, selected[0])"
        >
          <span class="el-select__tags-text">{{
            selected[0].currentLabel
          }}</span>
        </c-tag>
        <c-tag
          v-if="selected.length > 1"
          :closable="false"
          :size="collapseTagSize"
          type="info"
          disable-transitions
        >
          <span class="el-select__tags-text">+ {{ selected.length - 1 }}</span>
        </c-tag>
      </span>
      <transition-group v-if="!collapseTags" @after-leave="resetInputHeight">
        <c-tag
          v-for="item in selected"
          :key="getValueKey(item)"
          :closable="!selectDisabled"
          :size="collapseTagSize"
          :hit="item.hitState"
          type="info"
          disable-transitions
          @close="deleteTag($event, item)"
        >
          <span class="el-select__tags-text">{{ item.currentLabel }}</span>
        </c-tag>
      </transition-group>

      <input
        v-if="filterable"
        ref="input"
        v-model="query"
        type="text"
        class="el-select__input"
        :class="[selectSize ? `is-${selectSize}` : '']"
        :disabled="selectDisabled"
        :autocomplete="autoComplete || autocomplete"
        :style="{
          'flex-grow': '1',
          width: inputLength / (inputWidth - 32) + '%',
          'max-width': inputWidth - 42 + 'px'
        }"
        @focus="handleFocus"
        @blur="softFocus = false"
        @click.stop
        @keyup="managePlaceholder"
        @keydown="resetInputState"
        @keydown.down.prevent="navigateOptions('next')"
        @keydown.up.prevent="navigateOptions('prev')"
        @keydown.enter.prevent="selectOption"
        @keydown.esc.stop.prevent="visible = false"
        @keydown.delete="deletePrevTag"
        @compositionstart="handleComposition"
        @compositionupdate="handleComposition"
        @compositionend="handleComposition"
        @input="debouncedQueryChange"
      />
    </div>
    <c-input
      :id="id"
      ref="reference"
      v-model="selectedLabel"
      type="text"
      :placeholder="currentPlaceholder"
      :name="name"
      :autocomplete="autoComplete || autocomplete"
      :size="selectSize"
      :disabled="selectDisabled"
      :readonly="readonly"
      :validate-event="false"
      :class="{ 'is-focus': visible }"
      @focus="handleFocus"
      @blur="handleBlur"
      @keyup.native="debouncedOnInputChange"
      @keydown.native.down.stop.prevent="navigateOptions('next')"
      @keydown.native.up.stop.prevent="navigateOptions('prev')"
      @keydown.native.enter.prevent="selectOption"
      @keydown.native.esc.stop.prevent="visible = false"
      @keydown.native.tab="visible = false"
      @paste.native="debouncedOnInputChange"
      @mouseenter.native="inputHovering = true"
      @mouseleave.native="inputHovering = false"
    >
      <template v-if="$slots.prefix" slot="prefix">
        <slot name="prefix" />
      </template>
      <template slot="suffix">
        <i
          v-show="!showClose"
          :class="[
            'el-select__caret',
            'el-input__icon',
            'el-icon-' + iconClass
          ]"
        />
        <i
          v-if="showClose"
          class="el-select__caret el-input__icon el-icon-circle-close"
          @click="handleClearClick"
        />
      </template>
    </c-input>
    <transition
      name="el-zoom-in-top"
      @before-enter="handleMenuEnter"
      @after-leave="doDestroy"
    >
      <el-select-menu
        v-show="visible && emptyText !== false"
        ref="popper"
        :append-to-body="popperAppendToBody"
      >
        <c-scrollbar
          v-show="options.length > 0 && !loading"
          ref="scrollbar"
          tag="ul"
          wrap-class="el-select-dropdown__wrap"
          view-class="el-select-dropdown__list"
          :class="{
            'is-empty': !allowCreate && query && filteredOptionsCount === 0
          }"
        >
          <Tree
            ref="tree"
            :key="key"
            :props="props"
            :load="getNextNode"
            :lazy-cache="lazyCache"
            :data="treeData"
            :lazy="lazy"
            :render-after-expand="renderAfterExpand"
            :default-expanded-keys="allLoadDefaultExpanded"
          />
        </c-scrollbar>
        <p
          v-if="
            emptyText &&
            (!allowCreate || loading || (allowCreate && options.length === 0))
          "
          class="el-select-dropdown__empty"
        >
          {{ emptyText }}
        </p>
      </el-select-menu>
    </transition>
  </div>
</template>

<script>
import request from '@/utils/request'
import SelectTree from '@cci/cp-select-tree'
export default {
  name: 'SelectTree',
  mixins: [SelectTree],
  props: {
    valueToLabelParams: {
      type: Object,
      default() {
        return {}
      }
    },
    props: {
      type: Object,
      default() {
        return {
          children: 'children',
          label: 'name',
          value: 'id',
          icon: 'icon',
          disabled: 'disabled',
          isLeaf: 'leaf'
        }
      }
    },
    lazy: {
      type: Boolean,
      default: true
    },
    getLabelByIdFn: Function,
    renderAfterExpand: {
      type: Boolean,
      default: true
    },
    treeData: {
      type: Array,
      default: () => []
    },
    isLoadAllNode: {
      type: Boolean,
      default: false
    },
    // 下拉树参数
    treeParams: {
      type: Object,
      default() {
        return {
          get: {
            url: '',
            // url: "/v1/sys/function/findNextChildNodeTree",
            nextNodeKey: 'node',
            nextNodeValue: '',
            idKey: 'id',
            getNextNode: Function
            // getNextNode 自定义获取节点函数
            /**
             * getNextNode(params, data) {
             *    params.node = data['id']
             *    params.groupId = '1'
             *    return request({
             *      url: ''
             *      methods: 'get'
             *    })
             * }
             */
          }
        }
      }
    }
  },
  data() {
    return {
      isSearch: false,
      assistanceParams: {}
    }
  },
  methods: {
    // 根据 id 查找 label
    getLabelById(value) {
      return new Promise((resolve) => {
        if (this.getLabelByIdFn) {
          this.getLabelByIdFn(value)
            .then((data) => {
              resolve(data)
            })
            .catch(() => {
              resolve(value)
            })
        } else {
          // const { url, idKey } = this.valueToLabelParams
          // if (!url || !value) return resolve(value)
          // const params = {}
          // params[idKey] = value
          // request({
          //   url,
          //   methods: 'get',
          //   params
          // }).then(({ data }) => {
          //   resolve(data?.name)
          // })

          // 上级节点获取数据
          const { fullPath } = this.valueToLabelParams.prevNode
          const fullPathArr = fullPath.split('/')
          const name = fullPathArr[fullPathArr.length - 2]
          resolve(name)
        }
      })
    },
    // 重新加载下拉树后操作
    reload(data = {}, isSearch = false) {
      this.assistanceParams = data
      this.isSearch = !!isSearch
      this.refresh()
    },
    // 获取下一次树节点
    getNextNode({ data, level }, resolve) {
      if (level > 0 && (this.isLoadAllNode || this.isSearch)) {
        data = data[this.props.children]
        data && this.formatData(data, resolve)
      } else {
        // 非一次性获取
        // 一次性获取 顶层节点
        const params = {}
        const get = this.treeParams && this.treeParams.get
        if (get) {
          if (Object.keys(this.assistanceParams).length) {
            Object.keys(this.assistanceParams).forEach((k) => {
              params[k] = this.assistanceParams[k]
            })
          }
          if (level > 0 && get.nextNodeKey && get.idKey) {
            params[get.nextNodeKey] = data[get.idKey]
          }
          ;(
            (get.getNextNode && get.getNextNode(params, data)) ||
            request({
              url: get.url,
              method: 'get',
              params
            })
          )
            .then(({ data }) => {
              this.handleNoData(level, data)
              // 搜索 添加展开节点
              this.formatData(data, resolve)
              this.isSearch && this.allLoadExpand(data)
            })
            .catch(() => {
              this.handleNoData(level)
            })
        }
      }
    },
    handleNoData(level, data) {
      // 顶层 没有数据，或者数据为空
      if (
        level === 0 &&
        (!data || (Array.isArray(data) && data.length === 0))
      ) {
        this.$emit('selectTree-empty')
      }
    }
  }
}
</script>
